package com.myplans.client.controller;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.myplans.client.HistoryTokens;
import com.myplans.client.Presenter;
import com.myplans.client.UserUtil;
import com.myplans.client.event.AddPlanEvent;
import com.myplans.client.event.AddPlanEventHandler;
import com.myplans.client.event.SearchEvent;
import com.myplans.client.event.SearchEventHandler;
import com.myplans.client.event.SignInUserEvent;
import com.myplans.client.event.SignInUserEventHandler;
import com.myplans.client.event.SignUpUserEvent;
import com.myplans.client.event.SignUpUserEventHandler;
import com.myplans.client.event.UpdateUserEvent;
import com.myplans.client.event.UpdateUserEventHandler;
import com.myplans.client.event.ViewPlanEvent;
import com.myplans.client.event.ViewPlanEventHandler;
import com.myplans.client.event.ViewUserEvent;
import com.myplans.client.event.ViewUserEventHandler;
import com.myplans.client.presenter.HomePresenter;
import com.myplans.client.presenter.ProfilePresenter;
import com.myplans.client.presenter.SearchPresenter;
import com.myplans.client.presenter.ViewPlanPresenter;
import com.myplans.client.presenter.ViewUserPresenter;
import com.myplans.client.service.PlanServiceAsync;
import com.myplans.client.service.UserServiceAsync;
import com.myplans.client.util.CookieManager;
import com.myplans.client.view.HomeView;
import com.myplans.client.view.ProfileView;
import com.myplans.client.view.SearchView;
import com.myplans.client.view.ViewPlanView;
import com.myplans.client.view.ViewUserView;
import com.myplans.shared.Plan;
import com.myplans.shared.User;


public class HomeController implements Presenter, ValueChangeHandler<String> {

	HandlerManager eventBus;
	UserServiceAsync userServiceAsync;
	PlanServiceAsync planServiceAsync;
	HasWidgets container;
	Plan plan;
	User user;
	String searchString;

	public HomeController(HandlerManager eventBus, UserServiceAsync userServiceAsync, PlanServiceAsync planServiceAsync) {
		History.addValueChangeHandler(this);
		this.eventBus = eventBus;
		this.userServiceAsync = userServiceAsync;
		this.planServiceAsync = planServiceAsync;
		bind();
	}

	private void bind() {
		eventBus.addHandler(SignInUserEvent.TYPE, new SignInUserEventHandler() {
			
			@Override
			public void onSignInUser(SignInUserEvent event) {
				userServiceAsync.signInUser(event.getEmail(), event.getPassword(), new AsyncCallback<User>() {
					
					@Override
					public void onSuccess(User user) {
						if (user != null) {
							UserUtil.user = user;
							CookieManager.setUserLoginCookies(user.getEmail(), user.getPassword());
							History.newItem(HistoryTokens.SIGNIN.getId());
						} else {
							Window.alert("Invalid user. Please try again.");
						}
					}
					
					@Override
					public void onFailure(Throwable user) {
						Window.alert("ERROR");
					}
				});
			}
		});
		eventBus.addHandler(SignUpUserEvent.TYPE, new SignUpUserEventHandler() {
			
			@Override
			public void onSignUpUser(SignUpUserEvent event) {
				userServiceAsync.signUpUser(event.getUser(), new AsyncCallback<User>() {
					
					@Override
					public void onSuccess(User user) {
						if (user != null) {
							UserUtil.user = user;
							CookieManager.setUserLoginCookies(user.getEmail(), user.getPassword());
							History.newItem(HistoryTokens.SIGNIN.getId());
						} else {
							Window.alert("FAILED");
						}
					}
					
					@Override
					public void onFailure(Throwable user) {
						Window.alert("ERROR");
					}
				});

			}
		}); 
		eventBus.addHandler(AddPlanEvent.TYPE, new AddPlanEventHandler() {
			
			@Override
			public void onAddPlan(AddPlanEvent event) {
				planServiceAsync.addPlan(event.getPlan(), new AsyncCallback<Plan>() {

							@Override
							public void onSuccess(Plan result) {
								History.newItem(HistoryTokens.HOME.getId());
							}

							@Override
							public void onFailure(Throwable caught) {
								Window.alert("Plan failed to be added");
							}
				});
			}
		});
		eventBus.addHandler(ViewPlanEvent.TYPE, new ViewPlanEventHandler() {
			
			@Override
			public void onViewPlan(ViewPlanEvent event) {
				plan = event.getPlan();
				History.newItem(HistoryTokens.VIEW_PLAN.getId());
			}
		});
		eventBus.addHandler(UpdateUserEvent.TYPE, new UpdateUserEventHandler() {
			
			@Override
			public void onUpdateUser(UpdateUserEvent updateUserEvent) {
				userServiceAsync.updateUser(updateUserEvent.getUser(), new AsyncCallback<User>() {
				
					@Override
					public void onSuccess(User result) {
						UserUtil.user = result;
						History.newItem(HistoryTokens.HOME.getId());
					}
					
					@Override
					public void onFailure(Throwable caught) {
						Window.alert("User failed to be updated");
					}
				});
			}
		});
		eventBus.addHandler(SearchEvent.TYPE, new SearchEventHandler() {
			
			@Override
			public void onSearch(SearchEvent searchEvent) {
				searchString = searchEvent.getSearchString();
				History.newItem(HistoryTokens.HOME.getId());
				History.newItem(HistoryTokens.SEARCH_RESULTS.getId());
			}
		});
		eventBus.addHandler(ViewUserEvent.TYPE, new ViewUserEventHandler() {
			
			@Override
			public void onViewUser(ViewUserEvent viewUserEvent) {
				user = viewUserEvent.getUser();
				History.newItem(HistoryTokens.VIEW_USER.getId());
			}
		});
	}

	@Override
	public void go(HasWidgets container) {
		this.container = container;

	}

	@Override
	public void onValueChange(ValueChangeEvent<String> event) {
		String token = event.getValue();
		if (token != null) {
			Presenter presenter = null;
			if (token.equals(HistoryTokens.HOME.getId())) {
				presenter = new HomePresenter(eventBus, new HomeView());
				((HomePresenter)presenter).setUsersService(userServiceAsync);
				((HomePresenter)presenter).setPlanService(planServiceAsync);
			}
			if (token.equals(HistoryTokens.SIGNIN.getId()) || 
				token.equals(HistoryTokens.LOGOUT.getId())) {
				History.newItem(HistoryTokens.HOME.getId());
			}
			if (token.equals(HistoryTokens.VIEW_PLAN.getId())) {
				if (plan == null) {
					History.newItem(HistoryTokens.HOME.getId());
					return;
				}
				presenter = new ViewPlanPresenter(eventBus, new ViewPlanView());
				((ViewPlanPresenter)presenter).setUsersService(userServiceAsync);
				((ViewPlanPresenter)presenter).setPlanService(planServiceAsync);
				((ViewPlanPresenter)presenter).setPlan(plan);
			}
			if (token.equals(HistoryTokens.VIEW_USER.getId())) {
				if (user == null) {
					History.newItem(HistoryTokens.HOME.getId());
					return;
				}
				presenter = new ViewUserPresenter(eventBus, new ViewUserView());
				((ViewUserPresenter)presenter).setUsersService(userServiceAsync);
				((ViewUserPresenter)presenter).setPlanService(planServiceAsync);
				((ViewUserPresenter)presenter).setUser(user);
			}
			if (token.equals(HistoryTokens.PROFILE.getId())) {
				presenter = new ProfilePresenter(eventBus, new ProfileView());
				((ProfilePresenter)presenter).setUsersService(userServiceAsync);
				((ProfilePresenter)presenter).setPlanService(planServiceAsync);
			}
			if (token.equals(HistoryTokens.SEARCH_RESULTS.getId())) {
				if (searchString == null) {
					History.newItem(HistoryTokens.HOME.getId());
					return;
				}
				presenter = new SearchPresenter(eventBus, new SearchView());
				((SearchPresenter)presenter).setUsersService(userServiceAsync);
				((SearchPresenter)presenter).setPlanService(planServiceAsync);
				((SearchPresenter)presenter).setSearchString(searchString);
			}
			if (token.equals(HistoryTokens.SIGNIN_WITH_FACEBOOK.getId())) {
				if (UserUtil.access_token != null) {
					userServiceAsync.getFbUser(UserUtil.access_token, new AsyncCallback<User>() {
						
						@Override
						public void onSuccess(User result) {
							UserUtil.user = result;
							CookieManager.setUserLoginCookies(result.getEmail(), result.getPassword());
							History.newItem(HistoryTokens.HOME.getId());
						}
						
						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub
							
						}
					});
				}
			}
			if (presenter != null) {
				presenter.go(container);
			}
		}

	}

}
